from io import StringIO

import bs4
import requests
from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMessageBox, QTableWidgetItem
from form import Ui_MainWindow
from browser import Browser
from bs4 import BeautifulSoup
import pandas as pd
import configparser



class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)


        # 学生姓名
        self.student_name = None

        # 创建 MyLogin 实例
        self.my_login = MyLogin()

        # 登录界面，将 MyLogin 界面显示绑定在 pushButtonLogin 按钮上
        self.pushButtonLogin.clicked.connect(self.show_my_login)
        # 查询分数
        self.pushButtonQueryScore.clicked.connect(self.query_score)
        # 查询课程
        self.pushButtonQueryCourse.clicked.connect(self.query_course)
        # 导出成绩
        self.pushButtonExportScore.clicked.connect(self.e_score)
        # 导出课程
        self.pushButtonExportCourse.clicked.connect(self.my_login.export_Course_Excel)

    def show_my_login(self):
        # 显示登录界面
        self.my_login.show()
        self.my_login.login_ask()

        # 创建定时器
        self.timer = QTimer()
        self.timer.timeout.connect(self.timeout)
        self.timer.start(1000)

    def timeout(self):
        # 停止计时
        self.timer.stop()

        # 隐藏界面
        self.my_login.hide()

        # 检查登录情况
        self.student_name = self.my_login.check()

        if self.my_login.check():
            QMessageBox.question(self, "登录提示", f"欢迎你，{self.student_name}", QMessageBox.Yes, QMessageBox.Yes)
            self.labelName.setText(f"您好，{self.student_name}")  # 设置用户名

        else:

            QMessageBox.question(self, "登录提示", "登录失败", QMessageBox.Yes, QMessageBox.Yes)

    def table_load(self, row_num, column_num, table: bs4.element.Tag, head=None):

        # 定义表格的行列
        self.tableWidget.setRowCount(row_num)
        self.tableWidget.setColumnCount(column_num)

        # 如果需要写入表头
        if head:
            head = ['编号', '学期', '课程编号', '课程名称', '学分', '总学时', '成绩', '获得学分', '课程绩点', '备注']
            for i in range(column_num):
                item = QTableWidgetItem(head[i])
                self.tableWidget.setItem(0, i, item)

        # 写入数据
        for i, row in enumerate(table.find_all('tr')):
            for j, cell in enumerate(row.find_all('td')):
                item = QTableWidgetItem(cell.text.strip())
                self.tableWidget.setItem(i, j, item)

    def query_course(self):
        args = self.my_login.getCourse()
        self.table_load(*args)

    def query_score(self):

        year = self.comboBoxYear.currentText()
        term = "{}{}".format(year, self.comboBoxTerm.currentIndex() + 1)

        print(f"查询学期为：{term}")
        args = self.my_login.getScore(term)
        if args is None:
            QMessageBox.question(self, "提示", "查询失败", QMessageBox.Yes, QMessageBox.Yes)
            return

        self.table_load(*args)

    def e_score(self):
        year = self.comboBoxYear.currentText()
        term = "{}{}".format(year, self.comboBoxTerm.currentIndex() + 1)
        self.my_login.export_Score_Excel(term)



class MyLogin(Browser):
    def __init__(self):
        super().__init__()

    def login_ask(self):

        reply = QMessageBox.question(self, "登录", "是否自动填充账号信息？", QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.Yes)

        if reply == QMessageBox.Yes:  # 自动填充
            self.auto_fill()

            self.runJS("document.getElementsByClassName('auth_login_btn primary full_width')[" "0].click();")

    def runJS(self, content):
        self.browser.page().runJavaScript(content)

    def auto_fill(self):

        # 创建一个配置解析器对象
        config = configparser.ConfigParser()
        # 读取配置文件
        config.read('user.ini')
        # 获取指定部分的指定选项的值
        username = config.get('account', 'username')
        password = config.get('account', 'password')

        j1 = f"document.getElementById('username').value = '{username}';"
        j2 = f"document.getElementById('password').value = '{password}';"
        self.runJS(j1)
        self.runJS(j2)

    def check(self):

        cookies = self.cookies

        url = "https://eas.wvpn.huat.edu.cn/default.aspx"

        payload = {}
        headers = {
            'authority': 'eas.wvpn.huat.edu.cn',
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
            'cache-control': 'no-cache',
            'cookie': '; '.join([f'{name}={value}' for name, value in cookies.items()]),
            'pragma': 'no-cache',
            'referer': 'https://cas.wvpn.huat.edu.cn/',
            'sec-ch-ua': '"Microsoft Edge";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
            'sec-ch-ua-mobile': '?0',
            'sec-ch-ua-platform': '"Windows"',
            'sec-fetch-dest': 'document',
            'sec-fetch-mode': 'navigate',
            'sec-fetch-site': 'same-site',
            'sec-fetch-user': '?1',
            'upgrade-insecure-requests': '1',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.55'
        }

        response = requests.request("GET", url, headers=headers, data=payload)
        soup = BeautifulSoup(response.text, 'html.parser')
        name = soup.find(id='ctl00_lblUserName')

        if name:
            self.student_name = name.text
            return name.text

        return False

    def fetch_course(self):

        cookies = self.cookies

        # 构建请求头，包含Cookie信息
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.47',  # User-Agent
            'Cookie': '; '.join([f'{name}={value}' for name, value in cookies.items()])
        }

        # API请求URL
        api_url = "https://eas.wvpn.huat.edu.cn/SelectResult/StudentCourseTable.aspx"

        # 发送GET请求到课表API
        response = requests.get(api_url, headers=headers)

        # 处理API响应
        if response.status_code == 200:
            course_schedule = response.text  # 这里假设API返回的是HTML内容
            # 在这里处理课表数据
            return course_schedule
        else:
            print("课表API请求失败")

    def fetch_score(self, term):
        cookies = self.cookies

        url = "https://eas.wvpn.huat.edu.cn/Grade/GradeQuery.aspx"

        payload = f'__VIEWSTATE=%2FwEPDwUJNTMyNTI5NTAxDxYCHhNWYWxpZGF0ZVJlcXVlc3RNb2RlAgEWAmYPZBYCAgMPZBYIAgEPDxYCHgdWaXNpYmxlaGRkAgIPZBYEAgMPDxYCHgRUZXh0BQkyMDIwNjI0NzZkZAIFDw8WAh8CBQnpu4Tlro%2Flk7JkZAIDD2QWBgIBD2QWCAIBDxAPFgYeDURhdGFUZXh0RmllbGQFDFllYXJUZXJtTmFtZR4ORGF0YVZhbHVlRmllbGQFClllYXJUZXJtSUQeC18hRGF0YUJvdW5kZ2QQFR4G5YWo6YOoGzIwMjMtMjAyNOWtpuW5tOesrOS4gOWtpuacnxsyMDIyLTIwMjPlrablubTnrKzkuozlrabmnJ8bMjAyMi0yMDIz5a2m5bm056ys5LiA5a2m5pyfGzIwMjEtMjAyMuWtpuW5tOesrOS6jOWtpuacnxsyMDIxLTIwMjLlrablubTnrKzkuIDlrabmnJ8bMjAyMC0yMDIx5a2m5bm056ys5LqM5a2m5pyfGzIwMjAtMjAyMeWtpuW5tOesrOS4gOWtpuacnxsyMDE5LTIwMjDlrablubTnrKzkuozlrabmnJ8bMjAxOS0yMDIw5a2m5bm056ys5LiA5a2m5pyfGzIwMTgtMjAxOeWtpuW5tOesrOS6jOWtpuacnxsyMDE4LTIwMTnlrablubTnrKzkuIDlrabmnJ8bMjAxNy0yMDE45a2m5bm056ys5LqM5a2m5pyfGzIwMTctMjAxOOWtpuW5tOesrOS4gOWtpuacnxsyMDE2LTIwMTflrablubTnrKzkuozlrabmnJ8bMjAxNi0yMDE35a2m5bm056ys5LiA5a2m5pyfGzIwMTUtMjAxNuWtpuW5tOesrOS6jOWtpuacnxsyMDE1LTIwMTblrablubTnrKzkuIDlrabmnJ8bMjAxNC0yMDE15a2m5bm056ys5LqM5a2m5pyfGzIwMTQtMjAxNeWtpuW5tOesrOS4gOWtpuacnxsyMDEzLTIwMTTlrablubTnrKzkuozlrabmnJ8bMjAxMy0yMDE05a2m5bm056ys5LiA5a2m5pyfGzIwMTItMjAxM%2BWtpuW5tOesrOS6jOWtpuacnxsyMDEyLTIwMTPlrablubTnrKzkuIDlrabmnJ8bMjAxMS0yMDEy5a2m5bm056ys5LqM5a2m5pyfGzIwMTEtMjAxMuWtpuW5tOesrOS4gOWtpuacnxsyMDEwLTIwMTHlrablubTnrKzkuozlrabmnJ8bMjAxMC0yMDEx5a2m5bm056ys5LiA5a2m5pyfGzIwMDktMjAxMOWtpuW5tOesrOS6jOWtpuacnxsyMDA5LTIwMTDlrablubTnrKzkuIDlrabmnJ8VHgMxMDAFMjAyMzEFMjAyMjIFMjAyMjEFMjAyMTIFMjAyMTEFMjAyMDIFMjAyMDEFMjAxOTIFMjAxOTEFMjAxODIFMjAxODEFMjAxNzIFMjAxNzEFMjAxNjIFMjAxNjEFMjAxNTIFMjAxNTEFMjAxNDIFMjAxNDEFMjAxMzIFMjAxMzEFMjAxMjIFMjAxMjEFMjAxMTIFMjAxMTEFMjAxMDIFMjAxMDEFMjAwOTIFMjAwOTEUKwMeZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZGQCCA8PFgIeC05hdmlnYXRlVXJsBTpIaXN0b3J5R3JhZGVRdWVyeS5hc3B4P1N0dWRJRD1IUTdrZWNmcE4zWkZKZ2laZTVKdVZBJTNkJTNkZGQCCg8PFgIfBgU4T3RoZXJHcmFkZVByaW50LmFzcHg%2FU3R1ZElEPUhRN2tlY2ZwTjNaRkpnaVplNUp1VkElM2QlM2RkZAIMDw8WAh8CBdQB5oKo6aKE57y05a2m6LS555qE5a2m5YiG5Li677yaNjguMO%2B8jOaCqOW3sue7j%2BS4iuivvueahOWtpuWIhuS4uu%2B8mjM3LjXvvIjljIXmi6zmraPluLjkuI7ph43kv67vvInjgILmjInnhaflrabmoKHopoHmsYLvvIzlvZPmgqjkuIror77lrabliIbotoXov4fpooTnvLTlrabotLnlrabliIbml7bvvIzmgqjpnIDopoHlr7notoXlh7rnmoTlrabliIbov5vooYzku5jotLnjgIJkZAIDDzwrABEDAA8WBB8FZx4LXyFJdGVtQ291bnRmZAEQFgAWABYADBQrAABkAgUPZBYCAgEPPCsAEQMADxYEHwVnHwcCAmQBEBYAFgAWAAwUKwAAFgJmD2QWBgIBD2QWEGYPZBYCZg8VAQExZAIBDw8WAh8CBQ80MjA3MjEyMzExMTgzMTVkZAICDw8WAh8CBQYzNjQuMDBkZAIDDw8WAh8CBQQyMDIzZGQCBA8PFgIfAgUBMWRkAgUPDxYCHwIFBENFVDRkZAIGDw8WAh8CBQMyMzFkZAIHDw8WAh8CBQYmbmJzcDtkZAICD2QWEGYPZBYCZg8VAQEyZAIBDw8WAh8CBQ80MjA3MjEyMjIxMTM0MDhkZAICDw8WAh8CBQYzODEuMDBkZAIDDw8WAh8CBQQyMDIyZGQCBA8PFgIfAgUBMmRkAgUPDxYCHwIFBENFVDRkZAIGDw8WAh8CBQMyMjJkZAIHDw8WAh8CBQYmbmJzcDtkZAIDDw8WAh8BaGRkAgUPFgIeA3NyYwUTL1Nlc3Npb25LZWVwZXIuYXNweGQYAwUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFK2N0bDAwJENvbnRlbnRQbGFjZUhvbGRlcjEkY2JTaG93VW5HZXRDcmVkaXQFJmN0bDAwJENvbnRlbnRQbGFjZUhvbGRlcjEkZ3ZPdGhlckdyYWRlDzwrAAwBCAIBZAUhY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyMSRkdkdyYWRlDzwrAAwBCGZk6zzCsMsszA8s50FRxSuTwgCjrttRvpS3UY%2ByMJ2vSak%3D&__EVENTVALIDATION=%2FwEdACoWAnZyASywti2zzJMkRM4BfowLo4LKwrt3qWGUuoRLrXKJS724A7T4eVSm7ItUgnebS16F9k%2BAUxBx%2BcWjT%2F%2B1SUixDibY2hjrsbrKi9MNtJHI%2FHF4yCfWv10QkTld3EvBP6O87gnkN6irrxRi9pmo6fY4NenpJYRCo3PNWQsCH7bJQZmVfefgWS1e3gHKMBOMmsFP8uLzsc5mpRPLkdrMYSpp4higHE2z55E3dnCip45gVED4maXpkbq18vc9NxpZka7XUaZnxZzL7YepZLNIsBoUcZzhQ%2BNqk5quUQfW3Eel73gAwDmQtXbTGnyWCqW24FFDOCoChAgJFt0idBY1qjibAcEfpDNLPPxDUP4uOlcoDOceP8Fw40Pk2kzF7xDsHYie8Ro9BockwT76IsDwBIytebqWNYwlTeyijDPpGQyhLL%2FoxUFb7wL67FWtIcFfdrSysLjaATnhN7kCXQg%2BGmy7vqrCLgTaq2H7WFp3gunaOJGjt66pV6U2bdE6Q1lv4D1Wg0BvwDmKm3k6ilaEuc5osY6gjUOzdYOK92AUVyAYQOR5yNP8YIoKviMcxFvo5l%2FzT1XGjzJwa1mW9iLS75rxUyIkPLG%2Fpo3BxO9e%2FOGdHmSI9zHzyFGhUVB6LZ65XrRPdPSTenCC4ax0h%2FwMObQqEE%2Fu4ZkNIjm4SzX1r1WmLUeINAPORW8Xv31c5svwf3qudbkdBRaxVhM9Rr3BdMGnHyL%2FgZf%2FTsBciPOcFdxHKNRQgnAZ6gUlmY1pr79pnXmMZhpfBKMqS1kGrKkWwOreEY1E5dDXt9t8bxhuuE8TfyN9mGHrUcJyDnHokLepVskdhUfcoW1JVEi2AMVUfumMhsF%2FOOESlpYtwS7RPVmkd0wTUs2586Y%2FxBt%2F1hcAmGdslYkQzZs%2F4qQSHW8%2FHcT7uGMXBD3zrEDqx8hCqw%3D%3D&ctl00%24ContentPlaceHolder1%24ddlTerm={term}&ctl00%24ContentPlaceHolder1%24btnQuery=%E6%9F%A5%E8%AF%A2'
        headers = {
            'authority': 'eas.wvpn.huat.edu.cn',
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
            'cache-control': 'no-cache',
            'content-type': 'application/x-www-form-urlencoded',
            'cookie': '; '.join([f'{name}={value}' for name, value in cookies.items()]),
            'origin': 'https://eas.wvpn.huat.edu.cn',
            'pragma': 'no-cache',
            'referer': 'https://eas.wvpn.huat.edu.cn/Grade/GradeQuery.aspx',
            'sec-ch-ua': '"Microsoft Edge";v="117", "Not;A=Brand";v="8", "Chromium";v="117"',
            'sec-ch-ua-mobile': '?0',
            'sec-ch-ua-platform': '"Windows"',
            'sec-fetch-dest': 'document',
            'sec-fetch-mode': 'navigate',
            'sec-fetch-site': 'same-origin',
            'sec-fetch-user': '?1',
            'upgrade-insecure-requests': '1',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.47'
        }

        response = requests.request("POST", url, headers=headers, data=payload)

        # 处理API响应
        if response.status_code == 200:
            score_table = response.text  # 这里假设API返回的是HTML内容
            # 在这里处理课表数据
            return score_table
        else:
            print("课表API请求失败")

    def getScore(self, term):

        content = self.fetch_score(term)
        soup = BeautifulSoup(content, 'html.parser')
        table: bs4.element.Tag = soup.find(id='ctl00_ContentPlaceHolder1_dvGrade')

        if table:
            print("查询成绩成功啦！")
        else:
            print("查询成绩失败！")
            return None

        # 获取成绩的行列
        row_num = len(table.find_all('tr'))
        column_num = len(table.find('tr').find_all('th'))
        head = ['编号', '学期', '课程编号', '课程名称', '学分', '总学时', '成绩', '获得学分', '课程绩点', '备注']

        return row_num, column_num, table, head

    def getCourse(self):

        content = self.fetch_course()
        soup = BeautifulSoup(content, 'html.parser')
        table = soup.find(id='ctl00_ContentPlaceHolder1_CourseTable')

        if table:
            print("查询课程成功啦！")

        # 获取课表的行列
        row_num = len(table.find_all('tr'))
        column_num = len(table.find('tr').find_all('td'))

        return row_num, column_num, table, None

    def export_Course_Excel(self):
        content = self.fetch_course()

        soup = BeautifulSoup(content, 'html.parser')
        table = soup.find(id='ctl00_ContentPlaceHolder1_CourseTable')

        try:
            html_str = StringIO(str(table))
            df = pd.read_html(html_str)[0]
            df.to_excel('课程表.xlsx')
        except Exception as e:
            print(e)

        QMessageBox.information(self, "提示", "导出成功！", QMessageBox.Yes)

    def export_Score_Excel(self, term):
        content = self.fetch_score(term)

        soup = BeautifulSoup(content, 'html.parser')
        table = soup.find(id='ctl00_ContentPlaceHolder1_dvGrade')

        try:
            html_str = StringIO(str(table))
            df = pd.read_html(html_str)[0]
            df.to_excel('成绩表.xlsx')
        except Exception as e:
            print(e)

        QMessageBox.information(self, "提示", "导出成功！", QMessageBox.Yes)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
